#########################异步#########################
import os
import json
import time
import uuid
from channels_websocket_demo2.settings import BASE_DIR
from channels.generic.websocket import AsyncWebsocketConsumer

class look_single_task_log(AsyncWebsocketConsumer):
    async def connect(self):
        # self.scope: 获取websocket连接的一些信息，例如path，json格式
        self.random = str(uuid.uuid1()).upper().replace('-', '')
        self.uuid_str = self.scope['url_route']['kwargs']['uuid_str']
        self.group_name = '%s_%s' % (self.random, self.uuid_str)

        # Join group 加入一个组
        await self.channel_layer.group_add(
            self.group_name,
            self.channel_name
        )

        await self.accept()

    async def disconnect(self, close_code):
        # Leave group 离开一个组
        await self.channel_layer.group_discard(
            self.group_name,
            self.channel_name
        )
        print(self.channel_name, "Leave group 离开一个组", self.group_name)

    # Receive message from WebSocket 接受客户端提交过来的数据
    async def receive(self, text_data):
        """
        接受并发送消息
        :param text_data: 接收前端发来的消息
        :return:
        """
        uuid_str = text_data
        filename = os.path.join(BASE_DIR, "demo_app/tailf_consumers.py")
        try:
            with open(filename, 'r', encoding="utf8") as f:
                print("%s 已打开文件,开始监控单任务日志：%s" % (uuid_str, filename))
                f.seek(0, 0)
                count = 0
                break_count = 0

                # 睡眠时间调大会阻塞
                while True:
                    line = f.readline()
                    if line:
                        # Send message to group 发送生成的信息到一个组
                        await self.channel_layer.group_send(
                            self.group_name,
                            {
                                # 必须指定type，否则报错：ValueError: Incoming message has no 'type' attribute
                                'type': 'tail_message',
                                'message': line
                            }
                        )
                        # Send message to WebSocket 发送生成的信息返回给客户端显示
                        await self.send(text_data=json.dumps({
                            'message': line
                        }))
                        # 控制输出速度
                        time.sleep(0.1)
                    if not line:
                        count += 1
                    # 读取行不为真大于等于30次，则暂停1秒
                    if count >= 30:
                        count = 0
                        break_count += 1
                        print("%s 第 %s 次进入1s等待..." % (uuid_str, break_count))
                        time.sleep(1)
                    # 若上述行为 大于等于 3次，则退出循环
                    if break_count >= 3:
                        print("%s 无内容行为 大于等于 3次，退出循环" % uuid_str)
                        break

            # 不会阻塞
            # for i in range(1000):
            #     # Send message to group 发送生成的信息到一个组
            #     await self.channel_layer.group_send(
            #         self.group_name,
            #         {
            #             # 必须指定type，否则报错：ValueError: Incoming message has no 'type' attribute
            #             'type': 'tail_message',
            #             'message': i
            #         }
            #     )
            #     # Send message to WebSocket 发送生成的信息返回给客户端显示
            #     await self.send(text_data=json.dumps({
            #         'message': i
            #     }))

            # 跳出循环后 发送关闭websocket信号给客户端
            print("%s 主动向客户端发送关闭websocket信号" % uuid_str)
            await self.close()
        except Exception as e:
            # 客户端主动关闭页面后，进程90秒内还存在，当发送close()时，会触发异常，因为客户端已经不在线了
            # <WebSocketProtocol client=['xxx.xxx.xxx.xxx', 62535] path=b'/look_single_task_log/'>
            print("%s 实时监控单任务日志文件异常：%s" % (uuid_str, e))
            await self.close()

    # Receive message from group
    # 函数名对应上面的 type 字段值
    # 可以什么都不做，为了避免报错：ValueError: Incoming message has no 'type' attribute
    # 也可以再次返回组内的消息给加入该组的前端
    # 这里无法主动关闭websocket连接
    async def tail_message(self, event):
        pass

        # message = event['message']
        # Send message to WebSocket
        # await self.send(text_data=json.dumps({
        #     'message': message
        # }))
#########################异步#########################




#########################非异步#########################
# from channels.generic.websocket import WebsocketConsumer
# import json
# import time
# import os
# from channels_websocket_demo2.settings import BASE_DIR
#
# class look_single_task_log(WebsocketConsumer):
#     def connet(self):
#         self.accept()
#
#     def disconnect(self, close_code):
#         print("客户端主动发送关闭websocket信号")
#         print(close_code)
#         self.close()
#
#     def receive(self, text_data):
#         """
#         接受并发送消息
#         :param text_data: 接收前端发来的消息
#         :return:
#         """
#         uuid_str = text_data
#
#         filename = os.path.join(BASE_DIR, "demo_app/tailf_consumers.py")
#         try:
#             with open(filename, 'r', encoding="utf8") as f:
#                 print("%s 已打开文件,开始监控单任务日志：%s" % (uuid_str, filename))
#                 f.seek(0, 0)
#                 count = 0
#                 break_count = 0
#                 while True:
#                     line = f.readline()
#                     if line:
#                         self.send(text_data=json.dumps({'message': line}))
#                         # 控制输出速度
#                         time.sleep(0.1)
#                     if not line:
#                         count += 1
#                     # 读取行不为真大于等于30次，则暂停30秒
#                     if count >= 30:
#                         count = 0
#                         break_count += 1
#                         print("%s 第 %s 次进入30s等待..." % (uuid_str, break_count))
#                         time.sleep(3)
#                     # 若上述行为 大于等于 3次，则退出循环
#                     if break_count >= 3:
#                         print("%s 无内容行为 大于等于 3次，退出循环" % uuid_str)
#                         break
#                 # 跳出循环后 发送关闭websocket信号给客户端
#                 print("%s 主动向客户端发送关闭websocket信号" % uuid_str)
#                 self.close()
#         except Exception as e:
#             # 客户端主动关闭页面后，进程90秒内还存在，当发送close()时，会触发异常，因为客户端已经不在线了
#             # <WebSocketProtocol client=['xxx.xxx.xxx.xxx', 62535] path=b'/look_single_task_log/'>
#             print("%s 实时监控单任务日志文件异常：%s" % (uuid_str, e))
#             self.close()
#########################非异步#########################
